#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sqlite3.h>
#include <signal.h>
#include <time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "common.h"

int main(int argc, char *argv[])
{
	int listenfd, connectfd;
	struct sockaddr_in server_addr;
	pid_t pid;
	sqlite3 *db;
	
	if (argc < 3)
	{
		printf("Usage : %s <ip> <port>\n", argv[0]);
		exit(-1);
	}
	if (sqlite3_open(DATABASE, &db) != SQLITE_OK)
	{
		printf("error : %s\n", sqlite3_errUSER_INFO(db));
		exit(-1);
	}
	if ((listenfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
	{
		err_log("fail to socket");
		exit(-1);
	}

	bzero(&server_addr, sizeof(server_addr));
	server_addr.sin_family = PF_INET;
	server_addr.sin_addr.s_addr = inet_addr(argv[1]);
	server_addr.sin_port = htons(atoi(argv[2]));

	if (bind(listenfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
	{
		err_log("fail to bind");
		exit(-1);
	}
	if (listen(listenfd, 5) < 0)
	{
		err_log("fail to listen");
		exit(-1);
	}

	signal(SIGCHLD, SIG_IGN);// 避免僵尸进程
	while ( 1 )
	{
		if ((connectfd = accept(listenfd, NULL, NULL)) < 0)
		{
			err_log("fail to accept");
			exit(-1);
		}
		if ((pid = fork()) < 0)
		{
			err_log("fail to fork");
			exit(-1);
		}
		if (pid == 0)
		{
		    close(listenfd);
			do_client(connectfd, db);
		}
		close(connectfd);
	}
	return 0;
}

/***************************************************************************
 * 功能：
 *		打开/创建数据库
 * 参数：
 *      @db_name: 数据库名称
 *      @db     : 记录打开的数据库句柄
 * 返回值： 
 *		成功 0 ， 失败 -1 
 ***************************************************************************/
int create_open_database(const char* db_name, sqlite3** db)
{
	char *errmsg;
	char sql[128] = {0};

	if(sqlite3_open(db_name, db) != SQLITE_OK) {
		err_log(sqlite3_errmsg(*db));
		return -1;
	} else {
		printf("create or open %s success\n", db_name);
	}
	if(strcmp(db_name, USERINFO) == 0) {
		memset(sql, 0, sizeof(sql));
		sprintf(sql, "create table if not exists %s(id integer, name text, passwd text);", db_name);
		if(sqlite3_exec(*db, sql, NULL, NULL, &errmsg) != SQLITE_OK) {
			err_log(sqlite3_errmsg(*db));
			return -1;
		}
	} else if(strcmp(db_name, SOURCE) == 0) {
		memset(sql, 0, sizeof(sql));
		sprintf(sql, "create table if not exists %s(id integer, name text, size integer);", db_name);
		if(sqlite3_exec(*db, sql, NULL, NULL, &errmsg) != SQLITE_OK) {
			err_log(sqlite3_errmsg(*db));
			return -1;
		}
	}
	
	return 0;
}

// 管理员注册
void do_register(int connectfd, USER_INFO *user_info, sqlite3 *db)
{
	char sqlstr[128] = {0};
	char *errmsg;

	sprintf(sqlstr, "insert into usr values('%s', '%s', '%s')", user_info->name, user_info->password, user_info->no);
	
	if(sqlite3_exec(db, sqlstr, NULL, NULL, &errmsg) != SQLITE_OK)
	{
		sprintf(user_info->data, "user %s already exist!!!", user_info->name);
	}
	else
	{
		strcpy(user_info->data, "OK");
	}

	send(connectfd, user_info, sizeof(user_info), 0);

	return;
}

void do_login(int connectfd, USER_INFO *user_info, sqlite3 *db)
{
	char sqlstr[128] = {0};
	char *errmsg, **result;
	int nrow, ncolumn;

	sprintf(sqlstr, "select * from usr where name = '%s' and password = '%s'", user_info->name, user_info->password);
	if(sqlite3_get_table(db, sqlstr, &result, &nrow, &ncolumn, &errmsg) != SQLITE_OK)
	{
		err_log(errmsg);
	}
	if(nrow == 0)
	{
		strcpy(user_info->data, "name or password is wrong!!!");
	}
	else
	{
		strncpy(user_info->data, "OK", 3);
	}

	send(connectfd, user_info, sizeof(USER_INFO), 0);
	return;
}

void do_query(int connectfd, USER_INFO *user_info, sqlite3 *db)
{
	puts("query");
	char sqlstr[128], *errmsg;
	int found = 0;
	char date[128], word[128];

	strcpy(word, user_info->data);

	sprintf(sqlstr, "insert into record values('%s', '%s', '%s')", USER_INFO->name, date, word);
		if(sqlite3_exec(db, sqlstr, NULL, NULL, &errUSER_INFO) != SQLITE_OK)
		{
			printf("error : %s\n", errUSER_INFO);
		}
	}
	else
	{
		strcpy(USER_INFO->data, "not found");
	}
	send(connectfd, USER_INFO, sizeof(USER_INFO), 0);
	return;
}

void do_history(int connectfd, USER_INFO *USER_INFO, sqlite3 *db)
{
	char sqlstr[128], *errUSER_INFO;

	sprintf(sqlstr, "select * from record where name = '%s'", USER_INFO->name);
	if (sqlite3_exec(db, sqlstr, history_callback, (void *)&connectfd, &errUSER_INFO) != SQLITE_OK)
	{
		printf("error : %s\n", errUSER_INFO);
		sqlite3_free(errUSER_INFO);
	}
	USER_INFO->data[0] = '\0';
	send(connectfd, USER_INFO, sizeof(USER_INFO), 0);
	
	return;
}
int history_callback(void *arg, int f_num, char **f_value, char **f_name)
{
	int connectfd;
	USER_INFO USER_INFO;
	connectfd = *(int *)arg;
	sprintf(USER_INFO.data, "%s : %s", f_value[1], f_value[2]);  // name  date word
	send(connectfd, &USER_INFO, sizeof(USER_INFO), 0);
	return 0;
}

void getdata(char data[])
{
	time_t t;
	struct tm *tp;
	time(&t);
	tp = localtime(&t);
	sprintf(data, "%d-%d-%d %d:%d:%d", 
		tp->tm_year + 1900, tp->tm_mon +1, tp->tm_mday, 
		tp->tm_hour, tp->tm_min, tp->tm_sec);
}


void do_client(int connectfd, sqlite3 *db)
{

	USER_INFO user_info;
	while (recv(connectfd, &user_info, sizeof(USER_INFO), 0) > 0)  // receive request
	{
		printf("type = %d\n", USER_INFO.type);
		printf("type = %s\n", USER_INFO.data);
		switch ( user_info.type )
		{
		case R :
			do_register(connectfd, &user_info, db);
			break;
		case L :
			do_login(connectfd, &user_info, db);
			break;
		case Q :
			do_query(connectfd, &user_info, db);
			break;
		case A :
			do_add(connectfd, &user_info, db);
			break;
		case M :
			do_modify(connectfd, &user_info, db);
			break;		
		case D :
			do_delete(connectfd, &user_info, db);
			break;
		}
	}
	printf("client quit\n");
	exit(0);
	return;
}
